# -*- coding: utf-8 -*-
##############################################################################
#
#    OpenERP, Open Source Management Solution
#    Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
#
#    This program is free software: you can redistribute it and/or modify
#    it under the terms of the GNU Affero General Public License as
#    published by the Free Software Foundation, either version 3 of the
#    License, or (at your option) any later version.
#
#    This program is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU Affero General Public License for more details.
#
#    You should have received a copy of the GNU Affero General Public License
#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
from openerp.osv import osv, fields
import time
import base64
from openerp.tools.translate import _
from datetime import datetime
import logging
from openerp.tools import float_round, float_is_zero, float_compare
_logger = logging.getLogger(__name__)

class currency_inflation(osv.osv):
    _name = 'currency.inflation'
    _description = 'Currency Inflation'
    
    def _get_default_account(self, cr, uid, ids, field_name, arg, context=None):
        result = {}
        for rec in self.browse(cr, uid, ids, context=context):
            def_account = rec.journal_account.name
            result[rec.id] = def_account
        return result
    
    _columns = {
        'name': fields.char('Name', readonly=True),
        'journal_account': fields.many2one('account.journal', 'Journal Name'),
        'default_account': fields.function(_get_default_account, type='many2one', relation='account.account', string='Default Account'),
        'journal_account_amount': fields.float('Total Amount'),
        'date_prev': fields.date("Previous Date"),
        'date_curr': fields.date("Current Date"),
        'exrate_prev': fields.float('Previous Exrate', digits=(12,6)),
        'exrate_curr': fields.float('Current Exrate', digits=(12,6)),
        'state': fields.selection([('draft','Draft'),('posted','Posted'),('cancelled','Cancelled')],'State'),
        'move_id': fields.many2one('account.move', 'Currency Gain/Loss Entry'),
        'move_ids': fields.related('move_id','line_id', type='one2many', relation='account.move.line', string='Journal Items', readonly=True),
    }
    
    def onchange_journal_account(self, cr, uid, ids, journal_id, default_acc, context=None):
        if context is None:
            context = {}
        res = {}
        if not journal_id:
            return res
        
        acc_journal = self.pool.get('account.journal')
        for journal in acc_journal.browse(cr, uid, journal_id, context=context):
            res['value'] = {default_acc: journal.default_debit_account_id.id or journal.default_credit_account_id.id}

        return res
    
    def set_to_draft(self, cr, uid, ids, context=None):
        if context is None:
            context = {}
           
        return self.write(cr, uid, ids, {'state': 'draft'}, context=context)
    
    def unapprove_curr_inflation(self, cr, uid, ids, context=None):
        context = dict(context or {})
        move_obj = self.pool.get('account.move')
        inflation_line_obj = self.pool.get('currency.inflation.line')
        
        for line in self.browse(cr, uid, ids, context=context):
            if line.move_id:
                move_obj.button_cancel(cr, uid,[line.move_id.id,], context=context)
                move_obj.unlink(cr, uid, line.move_id.id, context=context)
                self.write(cr, uid, line.id, {'move_id': False, 'state': 'cancelled'}, context=context)

        return True
    
    def approve_curr_inflation(self, cr, uid, ids, context=None):  
        context = dict(context or {})
        period_obj = self.pool.get('account.period')
        move_obj = self.pool.get('account.move')
        move_line_obj = self.pool.get('account.move.line')
        seq_obj = self.pool.get('ir.sequence')
        
        for line in self.browse(cr, uid, ids, context=context):
            cur_date = line.date_curr
            period_ids = period_obj.find(cr, uid, cur_date, context=context)
            company_currency = line.journal_account.company_id.currency_id
            current_currency = line.journal_account.default_debit_account_id.currency_id or line.journal_account.default_credit_account_id.currency_id or company_currency
            journal_id = line.journal_account
            account_id = line.journal_account.default_debit_account_id or line.journal_account.default_credit_account_id
            amount_before = (line.journal_account_amount / line.exrate_prev)
            amount_before = float_round(amount_before, precision_rounding= current_currency.rounding)
            amount_before = round(amount_before,self.pool.get('decimal.precision').precision_get(cr, uid, 'Account'))
        
            amount_after = (line.journal_account_amount / line.exrate_curr)
            amount_after = float_round(amount_after, precision_rounding= current_currency.rounding)
            amount_after = round(amount_after,self.pool.get('decimal.precision').precision_get(cr, uid, 'Account'))
        
            amount_diff = amount_after - amount_before
            amount_diff_currency = amount_diff * line.exrate_curr
            amount_diff_currency = float_round(amount_diff_currency, precision_rounding= current_currency.rounding)
            amount_diff_currency = round(amount_diff_currency,self.pool.get('decimal.precision').precision_get(cr, uid, 'Account'))
        
            sign = (amount_diff >= 0 and 1) or -1
            
            reference = account_id.name
            period_id = period_ids and period_ids[0] or False
            name = '/'
            
            if not journal_id.company_id.property_currency_gain_loss.id:
                raise osv.except_osv(_('Invalid action !'), _('Please define Currency Gain Loss Account for Company first before proceed!'))
            
            if not journal_id.default_debit_account_id:
                raise osv.except_osv(_('Invalid action !'), _('Please define Default Debit Account for %s journal first before proceed!') % (journal_id.name,))
            
            if not journal_id.default_credit_account_id:
                raise osv.except_osv(_('Invalid action !'), _('Please define Default Credit Account for %s journal first before proceed!') % (journal_id.name,))
            
            if period_id:
                c = dict(context)
                c.update({'fiscalyear_id': period_obj.browse(cr, uid, period_id, context=context).fiscalyear_id.id})
                name = seq_obj.next_by_id(cr, uid, journal_id.sequence_id.id, context=c)
            
            move_vals = {
                'name': name,
                'date': cur_date,
                'ref': '/',
                'period_id': period_id,
                'journal_id': journal_id.id,
                }

            move_id = move_obj.create(cr, uid, move_vals, context=context)

            if amount_diff < 0:
                move_line_obj.create(cr, uid, {
                    'name': '/',
                    'ref': name,
                    'move_id': move_id,
                    'account_id': journal_id.company_id.property_currency_gain_loss.id,
                    'debit': abs(amount_diff) or 0.0,
                    'credit': 0.0,
                    'period_id': period_ids and period_ids[0] or False,
                    'journal_id': journal_id.id,
                    'currency_id': False,
                    'amount_currency': False,
                    'date': cur_date,
                })
                move_line_obj.create(cr, uid, {
                    'name': reference,
                    'ref': reference,
                    'move_id': move_id,
                    'account_id': account_id.id,
                    'credit': abs(amount_diff) or 0.0,
                    'debit': 0.0,
                    'period_id': period_ids and period_ids[0] or False,
                    'journal_id': journal_id.id,
                    'currency_id': (company_currency.id != current_currency.id and current_currency.id) or False,
                    'amount_currency': (company_currency.id != current_currency.id and amount_diff_currency) or False,
                    'date': cur_date,
                })
                
            elif amount_diff >= 0:
                move_line_obj.create(cr, uid, {
                    'name': reference,
                    'ref': reference,
                    'move_id': move_id,
                    'account_id': account_id.id,
                    'credit': 0.0,
                    'debit': abs(amount_diff) or 0.0,
                    'period_id': period_ids and period_ids[0] or False,
                    'journal_id': journal_id.id,
                    'currency_id': (company_currency.id != current_currency.id and current_currency.id) or False,
                    'amount_currency': (company_currency.id != current_currency.id and amount_diff_currency) or False,
                    'date': cur_date,
                })
                move_line_obj.create(cr, uid, {
                    'name': '/',
                    'ref': name,
                    'move_id': move_id,
                    'account_id': journal_id.company_id.property_currency_gain_loss.id,
                    'debit': 0.0,
                    'credit': abs(amount_diff) or 0.0,
                    'period_id': period_ids and period_ids[0] or False,
                    'journal_id': journal_id.id,
                    'currency_id': False,
                    'amount_currency': False,
                    'date': cur_date,
                }) 
                
            self.write(cr, uid, line.id, {'name': name, 'move_id': move_id, 'state': 'posted'}, context=context)        
        
        return True